home *** CD-ROM | disk | FTP | other *** search
- /*---------------------------------------------------------------------*\
- | |
- | CPP -- a stand-alone C preprocessor |
- | Copyright (c) 1993 Hacker Ltd. Author: Scott Bigham |
- | |
- | Permission is granted to anyone to use this software for any purpose |
- | on any computer system, and to redistribute it freely, with the |
- | following restrictions: |
- | - No charge may be made other than reasonable charges for repro- |
- | duction. |
- | - Modified versions must be clearly marked as such. |
- | - The author is not responsible for any harmful consequences of |
- | using this software, even if they result from defects therein. |
- | |
- | main.c -- kick it all off |
- \*---------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <time.h>
- #include <unistd.h>
- #include "global.h"
- #include "ztype.h"
- #include "patchlev.h"
-
- #define DEFAULT_CONFIG_NAME "cpp_defs.h"
-
- FILE *outf = stdout;
- FILE *inf = NULL;
- char *argv0;
- char **I_list;
- char date_string[12], time_string[9];
- int nerrs;
-
- int sl_style = SL_NORMAL,
- keep_comments = 0,
- do_trigraphs = 0,
- ansi = 0,
- w_bad_chars = 1,
- w_nest_cmts = 0,
- f_cpp_cmts = 0,
- w_bad_concat = 1;
-
- int in_config_file = 0;
- static char *config_file_name = NULL;
- static char stdin_name[] = STDIN_NAME;
-
- int fluff_mode = 0;
-
- static void usage()
- {
- fprintf(stderr, "usage: %s [-Dname[=value]...] [-Uname] "
- "[ infile [ outfile ] ]\n", argv0
- );
- exit(1);
- }
-
- static void dammit(sig)
- int sig;
- {
- fatal("received signal %d", sig);
- }
-
- static void setup_signals()
- {
- (void)signal(SIGHUP, dammit);
- (void)signal(SIGINT, dammit);
- (void)signal(SIGQUIT, dammit);
- (void)signal(SIGILL, dammit);
- (void)signal(SIGTRAP, dammit);
- (void)signal(SIGABRT, dammit);
- (void)signal(SIGEMT, dammit);
- (void)signal(SIGFPE, dammit);
- (void)signal(SIGBUS, dammit);
- (void)signal(SIGSEGV, dammit);
- (void)signal(SIGSYS, dammit);
- (void)signal(SIGPIPE, dammit);
- (void)signal(SIGALRM, dammit);
- (void)signal(SIGTERM, dammit);
- }
-
- /* add_include() -- adds |path| to the list of include directories */
- static void add_include(path)
- char *path;
- {
- static char **cur_I = NULL;
- static int n_I;
- ptrdiff_t dp;
-
- if (!cur_I)
- cur_I = I_list = (char **)mallok((n_I = 3) * sizeof (char *));
-
- if (cur_I - I_list == n_I) {
- dp = cur_I - I_list;
- I_list = reallok(I_list, (n_I *= 2) * sizeof (char *));
-
- cur_I = I_list + dp;
- }
- *cur_I++ = path;
- }
-
- /* long_option() -- parses long option |s| */
- static void long_option(s)
- char *s;
- {
- int yesno = 1;
- char *t;
-
- if (*s == 'W' || *s == 'f') {
- if (s[1] == 'n' && s[2] == 'o' && s[3] == '-') {
- yesno = 0;
- t = s + 4;
- } else
- t = s + 1;
- if (*s == 'W') { /* warnings */
- if (streq(t, "bad-chars"))
- w_bad_chars = yesno;
- else if (streq(t, "nested-comments"))
- w_nest_cmts = yesno;
- else if (streq(t, "bad-concat-tokens"))
- w_bad_concat = yesno;
- else {
- error("unknown -W option: %s", t);
- usage();
- }
- } else { /* actions */
- if (streq(t, "c++-comments"))
- f_cpp_cmts = yesno;
- else {
- error("unknown -f option: %s", t);
- usage();
- }
- }
- } else if (*s == 'X') {
- if (streq(s + 1, "fluff"))
- fluff_mode = 1;
- else {
- error("unknown -X option: %s", s + 1);
- usage();
- }
- } else if (streq(s, "ansi")) {
- ansi = 1;
- do_trigraphs ^= 1;
- } else {
- error("unrecognized option -%s", s);
- usage();
- }
- }
-
- /*
- opt_define() -- handle -Dfred. |s| points to the beginning of the token
- to #define.
- */
- static void opt_define(s)
- char *s;
- {
- Macro *M, *M1;
- char *t;
- unsigned int hv;
- int hmm = 0;
- static char one[] = "1";
-
- hv = hash_id(s, &t);
- if (*t && *t != '=') {
- error("malformed -D option \"%s\"", s);
- return;
- }
- if (*t)
- *t++ = '\0';
- else
- t = one;
- M1 = mk_Macro();
- M1->m_text = tokenize_string(t);
- if ((M = lookup(s, hv))) {
-
- /*
- guard against re-#definition of magic tokens or previously -U'd tokens
- */
- if (M->flags & (UNDEF | MAGIC))
- hmm = 1;
- if (hmm || !macro_eq(M1, M)) {
- if (!hmm)
- error("non-identical redefinition of \"%s\"", s);
- }
- free_Macro(M1);
- return;
- }
- hash_add(s, hv, M1);
- }
-
- /*
- opt_undefine() -- handle -Ufred. |s| points to the beginning of the token
- to #undef.
- */
- static void opt_undefine(s)
- char *s;
- {
- Token T;
- Macro *M;
- int was_there = 0;
- unsigned int hv;
-
- hv = hash_id(s, NULL);
- if ((M = lookup(s, hv))) {
- if (M->flags & MAGIC)
- return;
- if (M->m_text)
- free_tlist(M->m_text);
- was_there = 1;
- } else {
- M = mk_Macro();
- }
- M->m_text = NULL;
- M->flags |= UNDEF;
- if (!was_there)
- hash_add(s, hv, M);
- }
-
- /* do_cmdline_arg() -- process the command-line argument |s| */
- void do_cmdline_arg(arg)
- register char *arg;
- {
- switch (arg[1]) {
- case 'P':
- switch (arg[2]) {
- case '0':
- case '\0':
- sl_style = SL_NONE;
- break;
- case '1':
- sl_style = SL_NORMAL;
- break;
- case '2':
- sl_style = SL_LINE;
- break;
- default:
- error("bad argument '%c' to -P option", arg[2]);
- }
- break;
- case 'C':
- keep_comments = 1;
- break;
- case 'T':
- do_trigraphs ^= 1;
- break;
- case 'I':
- add_include(copy_filename(arg + 2, 0));
- break;
- case 'D':
- opt_define(arg + 2);
- break;
- case 'U':
- opt_undefine(arg + 2);
- break;
- case 'V':
- fprintf(stderr, "CPP -- C preprocessor v%d.%d.%d\n"
- "(c) 1993,94 Hacker Ltd., all rights reserved\n",
- CPP_VERSION, CPP_RELEASE, CPP_PATCHLEVEL);
- break;
- case 'S': /* already handled elsewhere */
- break;
- default:
- long_option(arg + 1);
- }
- }
-
- /* do_all_cmdline_args() -- process all command_line arguments */
- static int Argc = 0;
- static char **Argv = 0;
- int Argc_end = 0;
-
- void do_all_cmdline_args()
- {
- int i;
-
- for (i = 1; i < Argc && *Argv[i] == '-' && Argv[i][1] != '\0'; i++)
- do_cmdline_arg(Argv[i]);
- hash_clean_undef();
- Argc_end = i;
- }
-
- /* do_config_file() -- read standard #define's from config file */
- static void do_config_file()
- {
- char buf[128];
- register const char *s;
- register int len;
-
- if (!config_file_name) { /* default config file */
- if (!(s = getenv("LIB")))
- s = ".";
- while (*s) {
- len = strcspn(s, ",;");
- strncpy(buf, s, len);
- buf[len] = PATH_SEP;
- strcpy(buf + len + 1, DEFAULT_CONFIG_NAME);
- if (access(buf, R_OK) == 0) {
- in_config_file = 1;
- process_file(buf);
- in_config_file = 0;
- return;
- }
- s += len;
- if (*s)
- s++;
- }
- } else { /* user-specified config file */
- if (!*config_file_name)
- return;
- if (access(config_file_name, R_OK) != 0) {
- warning("cannot open user-specified config file \"%s\"",
- config_file_name);
- } else {
- in_config_file = 1;
- process_file(config_file_name);
- in_config_file = 0;
- }
- }
- }
-
- /* main() -- guess... */
- main(argc, argv)
- int argc;
- char **argv;
- {
- register int i;
- char *infnam;
- int num_Is = 3;
- register char **cur_I, *incdir;
- time_t t;
- struct tm *T;
-
- argv0 = argv[0];
- Z_type_init();
- hash_setup();
- cond_setup();
- setup_signals();
- time(&t);
- T = localtime(&t);
- strftime(date_string, 12, "%b %d %Y", T);
- strftime(time_string, 9, "%H:%M:%S", T);
- add_include((char *)0);
- /* first check for user-specified config file */
- for (i = 1; i < argc && *argv[i] == '-' && argv[i][1] != '\0'; i++)
- if (*argv[i] == '-' && argv[i][1] == 'S')
- config_file_name = argv[i] + 2;
- Argc = argc;
- Argv = argv;
- do_config_file();
- if (Argc_end == 0)
- do_all_cmdline_args();
- if ((incdir = getenv("INCLUDE"))) {
- char *s = incdir;
- size_t len;
-
- while (*s) {
- len = strcspn(s, ";,");
- add_include(copy_filename(s, len));
- s += len;
- if (*s)
- s++;
- }
- }
- add_include((char *)0);
- if (argc - i > 2) {
- error("too many arguments");
- usage();
- }
- if (i < argc && !streq(argv[i], "-"))
- infnam = copy_filename(argv[i], 0);
- else
- infnam = stdin_name;
- if (i + 1 < argc && (streq(argv[i + 1], "-") || !(outf = xfopen(argv[i + 1], "w"))))
- fatal("%s: cannot open output file %s", argv0, argv[i + 1]);
- process_file(infnam);
- free(infnam);
- for (cur_I = I_list + 1; *cur_I; cur_I++)
- if (*cur_I)
- free(*cur_I);
- free(I_list);
- fclose(outf);
- hash_free();
- cond_shutdown();
- tok_shutdown();
- if (nerrs > 0) {
- fprintf(stderr, "%d errors\n", nerrs);
- return 1;
- }
- return 0;
- }
-